﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Testing;
using Microsoft.CodeAnalysis.Testing.Verifiers;
using Microsoft.CodeAnalysis.Text;

namespace ErrorProne.NET.TestHelpers
{
    public static class CodeFixTestExtensions
    {
        public static TTest WithoutGeneratedCodeVerification<TTest>(this TTest test)
            where TTest : CodeFixTest<DefaultVerifier>
        {
            test.TestBehaviors |= TestBehaviors.SkipGeneratedCodeCheck;
            return test;
        }

        public static TTest WithConfigureAwaitAttributes<TTest>(this TTest test)
            where TTest : CodeFixTest<DefaultVerifier>
        {
            (string filename, string content) file = ("ConfigureAwaitAttributes.cs", @"// <auto-generated/>
[System.AttributeUsage(System.AttributeTargets.Assembly)]
internal sealed class UseConfigureAwaitFalseAttribute : System.Attribute { }

[System.AttributeUsage(System.AttributeTargets.Assembly)]
internal sealed class DoNotUseConfigureAwaitAttribute : System.Attribute { }
");

            test.TestState.Sources.Add(file);

            if (test.FixedState.Sources.Count > 0)
            {
                test.FixedState.Sources.Add(file);
            }

            if (test.BatchFixedState.Sources.Count > 0)
            {
                test.BatchFixedState.Sources.Add(file);
            }

            return test;
        }

        [System.AttributeUsage(System.AttributeTargets.Struct)]
        internal sealed class DoNotUseDefaultConstructionAttribute : System.Attribute
        {
            public DoNotUseDefaultConstructionAttribute(string? message = null) {}
        }

        [DoNotUseDefaultConstruction()]
        public struct FooBar
        {
            
        }

        [DoNotUseDefaultConstruction("Please use FooBar2.Create()")]
        public struct FooBar2
        {
            
        }
        
        public static TTest WithNonDefaultableAttribute<TTest>(this TTest test)
            where TTest : CodeFixTest<DefaultVerifier>
        {
            (string filename, string content) file = ("NonDefaultableAttribute.cs", @"// <auto-generated/>
[System.AttributeUsage(System.AttributeTargets.Struct)]
internal sealed class NonDefaultableAttribute : System.Attribute
{
    public NonDefaultableAttribute(string message = null) {}
}
");

            test.TestState.Sources.Add(file);

            if (test.FixedState.Sources.Count > 0)
            {
                test.FixedState.Sources.Add(file);
            }

            if (test.BatchFixedState.Sources.Count > 0)
            {
                test.BatchFixedState.Sources.Add(file);
            }

            return test;
        }

        public static TTest WithLargeStructThreshold<TTest>(this TTest test, int largeStructThreshold)
            where TTest : CodeFixTest<DefaultVerifier>
        {
            var content = $@"root = true

[*.{{cs,vb}}]
error_prone.large_struct_threshold = {largeStructThreshold}
";

            test.SolutionTransforms.Add((solution, projectId) =>
            {
                var documentId = DocumentId.CreateNewId(projectId, ".editorconfig");
                return solution.AddAnalyzerConfigDocument(documentId, ".editorconfig", SourceText.From(content), filePath: "/.editorconfig");
            });

            return test;
        }
    }
}
